#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

//演示：父进程回收单个子进程
//int main(){
//  pid_t id=fork();
//  if(id<0){
//    perror("fork");
//    return 1;
//  }else if(id==0){
//    int cnt=5;
//    while(cnt){
//      printf("I am a child,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);
//      --cnt;
//      sleep(1);
//    }
//    exit(0);
//  }else{
//    int cnt=10;
//    while(cnt){ 
//      printf("I am a father,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);
//      --cnt;
//      sleep(1);
//    }
//    pid_t ret=wait(NULL);
//    if(ret==id){
//      printf("wait success,ret:%d\n",ret);
//    }
//    sleep(5);
//  }
//  return 0;
//}

//循环等待：回收多进程
//正常回收版本
//#define N 10
//void RunChild(){
//  int cnt=5;
//  while(5){
//      printf("I am a child,pid:%d,ppid:%d\n",getpid(),getppid());
//      sleep(1);
//      --cnt;
//  }
//}
//int main(){
//  for(int i=0;i<N;++i){
//    pid_t id = fork();
//    if(id==0){
//      RunChild();
//      exit(0);//子进程走到这里也就不会再执行接下来的for循环了，因为父子代码块是共享的，当子进程走到这里进程会直接被终止
//    }
//    printf("create child process:%d success\n",id);//这句话只有父进程才会执行
//  } 
//  sleep(10);//每个子进程有效的执行时间只有前5s,5s之后子进程全部退出我们就可以看到有10个僵尸进程。
//
//  //接下来是进程等待
//  //注意：wait一次只能等待一个子进程退出，因此我们采用for循环
//  for(int i=0;i<N;++i){
//    //当任意一个子进程退出的时候，wait就会回收子进程
//    //如果任意一个子进程都不退出
//    pid_t id=wait(NULL);
//    if(id>0){
//      printf("wait %d success\n",id);
//    }
//  }
//  sleep(5);//方便子进程全部退出后观察父进程的状态
//  return 0;
//}
//子进程一直执行不被回收
//#define N 10
//void RunChild() {
//    while(1) {
//      //子进程一直执行
//        printf("I am Child Process, pid: %d, ppid:%d\n", getpid(), getppid());
//        sleep(1);
//    }
//}
//
//int main() {
//    for(int i = 0; i < N; i++) {
//        pid_t id = fork();
//        if(id == 0) {
//            RunChild();
//            exit(i);
//        } 
//        printf("create child process: %d success\n", id); 
//    }
//
//    for(int i = 0; i < N; i++) {
//        pid_t id = wait(NULL);//父进程在调用wait时会一直不返回，处于阻塞状态 
//        if(id > 0) {
//            printf("wait %d success\n", id);
//        }
//    }
//
//    sleep(5);
//    return 0;
//}


//获取子进程的退出结果
//单进程版本
//int main() {
//    pid_t pid = fork();
//    if (pid < 0) {
//        perror("fork error"); 
//        return 1;
//    } else if (pid == 0) {
//        // 子进程逻辑：
//        int cnt=3;
//        while (cnt) {
//            printf("Child [PID:%d] running, PPID:%d,cnt:%d\n", 
//                   getpid(), getppid(),cnt);
//            --cnt;
//            sleep(1);
//        }
//        exit(1);//子进程退出码设为1，方便退出后status获取子进程退出信息 
//    } else {
//        // 父进程逻辑：
//        int cnt = 5;
//        while (cnt--) {
//            printf("Parent [PID:%d] running, PPID:%d, cnt:%d\n", 
//                   getpid(), getppid(), cnt + 1);
//            sleep(1);
//        }
//        int status=0;
//        pid_t ret=waitpid(pid,&status,0);//Pid=-1,等待任一个子进程，与wait等效
//        if (ret == pid) {
//            //7F:0111 1111
//            //printf("Wait success! Child PID: %d,exit sig:%d,exit code:%d\n", ret,status&0x7F,(status>>8)&0xFF);
//          if(WIFEXITED(status)){
//            printf("进程是正常跑完的，退出码：%d\n",WEXITSTATUS(status));
//          }else{
//            printf("进程出现异常！\n");
//          }
//        }else{
//          printf("wait failed!\n");
//        }
//        sleep(3);  // 暂停以便观察进程状态
//    }
//    return 0;
//}
//多进程版本
//#define N 10
//void RunChild(){
//  int cnt=5;
//  while(cnt){
//      printf("I am a child,pid:%d,ppid:%d\n",getpid(),getppid());
//      sleep(1);
//      --cnt;
//  }
//}
//int main(){
//  for(int i=0;i<N;++i){
//    pid_t id = fork();
//    if(id==0){
//      RunChild();
//      exit(i);
//    }
//    printf("create child process:%d success\n",id);
//  } 
//
//  //接下来是进程等待
//  for(int i=0;i<N;++i){
//    int status=0;
//    pid_t id=waitpid(-1,&status,0);
//    if(id>0){
//      printf("wait %d success,exit code:%d\n",id,WEXITSTATUS(status));
//    }
//  }
//  sleep(5);
//  return 0;
//}

//非阻塞轮询
#define TASK_NUM 10
typedef void(*task_t)();
task_t tasks[TASK_NUM];
//所有任务
int AddTask();
void task1(){
  printf("执行打印日志的任务,pid:%d\n",getpid());
}
void task2(){
  printf("执行检测网络健康状态的任务,pid:%d\n",getpid());
}
void task3(){
  printf("绘制图像界面的任务,pid:%d\n",getpid());
}
//任务管理代码
void InitTask(){
  for(int i=0;i<TASK_NUM;++i)tasks[i]=NULL;
  AddTask(task1);
  AddTask(task2);
  AddTask(task3);
}
int AddTask(task_t t){
  int pos=0;
  for(;pos<TASK_NUM;++pos){
    if(!tasks[pos])break;
  }
  if(pos==TASK_NUM)return -1;
  tasks[pos]=t;
  return 0;
}
void DelTask(){

}
void CheckTask(){

}
void UpdateTask(){

}
void ExecuteTask(){
  for(int i=0;i<TASK_NUM;++i){
    if(!tasks[i])continue;
    tasks[i]();
  }
}

int main() {
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork error"); 
        return 1;
    } else if (pid == 0) {
        // 子进程逻辑：
        int cnt=5;
        while (cnt) {
            printf("Child [PID:%d] running, PPID:%d,cnt:%d\n", 
                   getpid(), getppid(),cnt);
            --cnt;
            sleep(1);
        }
        exit(1);
    } else {
        // 父进程逻辑：
        int status=0;
        InitTask();
        while(1){
          //轮询
          pid_t ret=waitpid(pid,&status,WNOHANG);//非阻塞
          if (ret > 0) {
            if(WIFEXITED(status)){
              printf("进程是正常跑完的，退出码：%d\n",WEXITSTATUS(status));
            }else{
              printf("进程出现异常！\n");
            }
            break;//说明等待成功，无需继续轮询
          }else if(ret < 0){
            printf("wait failed!\n");
            break;//说明等待失败，无需继续轮询
          }else{
            //父进程在等待过程中可以做的事情在这里实现
            ExecuteTask();
            usleep(500000);
          }
        }
        sleep(3);  // 暂停以便观察进程状态
    }
    return 0;
}
